package org.qhhc.hashmapandtable;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.*;

public class ConcurrentHashMapTest {
    private static final int THREAD_COUNT = 10;
    private static final int OPERATIONS = 100_000;

    public static void main(String[] args) throws InterruptedException {
        // 测试 ConcurrentHashMap
        testMapPerformance(new ConcurrentHashMap<>(), "ConcurrentHashMap");

        // 测试同步包装的 HashMap（对比性能）
        testMapPerformance(Collections.synchronizedMap(new HashMap<>()), "SynchronizedHashMap");
        // ================== 新增问题演示模块 ==================
        ConcurrentHashMap<Integer, String> problemMap = new ConcurrentHashMap<>();

        // 场景1：复合操作非原子性（检查后插入）
        testCompositeOperation(problemMap);

        // 场景2：迭代器弱一致性
        testWeakConsistency(problemMap);

        // 场景3：批量操作非原子性
        testBatchOperation(problemMap);

    }

    private static void testMapPerformance(Map<Integer, Integer> map, String label) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        long start = System.nanoTime();

        // 并发写入测试
        for (int i = 0; i < THREAD_COUNT; i++) {
            executor.submit(() -> {
                for (int j = 0; j < OPERATIONS; j++) {
                    map.put(j % 1000, j); // 故意哈希碰撞以增加锁竞争
                }
                latch.countDown();
            });
        }

        latch.await();
        long duration = (System.nanoTime() - start) / 1_000_000;
        System.out.printf("%s 写入耗时: %dms | 最终大小: %d\n", label, duration, map.size());

        // 并发读取测试
        start = System.nanoTime();
        executor.invokeAll(Collections.nCopies(THREAD_COUNT, () -> {
            for (int j = 0; j < OPERATIONS; j++) {
                map.get(j % 1000);
            }
            return null;
        }));
        duration = (System.nanoTime() - start) / 1_000_000;
        System.out.printf("%s 读取耗时: %dms\n", label, duration);

        executor.shutdown();
    }
    // 复合操作非原子性演示
    private static void testCompositeOperation(ConcurrentHashMap<Integer, String> map) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        final Integer targetKey = 9999;

        Runnable task = () -> {
            if (!map.containsKey(targetKey)) { // 检查操作
                try {
                    Thread.sleep(10); // 放大竞态窗口
                } catch (InterruptedException e) {}
                map.put(targetKey, Thread.currentThread().getName()); // 插入操作
            }
        };

        executor.submit(task);
        executor.submit(task);
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.SECONDS);

        System.out.println("\n[复合操作] 预期只插入1次，实际插入次数: " +
                (map.get(targetKey) != null ? 1 : 0) + " 最终值: " + map.get(targetKey));
    }

    // 迭代器弱一致性演示
    private static void testWeakConsistency(ConcurrentHashMap<Integer, String> map) {
        // 初始化数据
        for (int i = 0; i < 1000; i++) {
            map.put(i, "init-" + i);
        }

        new Thread(() -> {
            try {
                Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
                System.out.print("\n[弱一致性] 迭代元素数量变化：");
                int count = 0;
                while (it.hasNext()) {
                    it.next();
                    count++;
                    if (count == 500) { // 迭代到一半时触发修改
                        map.put(2000, "new-data"); // 添加新元素
                    }
                }
                System.out.print("迭代期间遍历到 " + count + " 个元素 | ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

        System.out.println("实际最终大小: " + map.size()); // 输出1001，但迭代可能只看到1000
    }

    // 批量操作非原子性演示
    private static void testBatchOperation(ConcurrentHashMap<Integer, String> map) throws InterruptedException {
        Map<Integer, String> tempMap = new HashMap<>();
        for (int i = 10000; i < 20000; i++) {
            tempMap.put(i, "batch-" + i);
        }

        new Thread(() -> {
            try {
                Thread.sleep(10); // 确保putAll已开始
                int inconsistentCount = 0;
                for (int i = 0; i < 10; i++) {
                    int size = map.size();
                    if (size > 1000 && size < 20000) { // 捕捉中间状态
                        inconsistentCount++;
                    }
                    Thread.sleep(1);
                }
                System.out.println("\n[批量操作] 检测到中间状态次数: " + inconsistentCount);
            } catch (InterruptedException e) {}
        }).start();

        map.putAll(tempMap); // 非原子批量操作
    }
}